home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / pcw.zip / LMENU.BAK < prev    next >
Text File  |  1991-12-21  |  19KB  |  354 lines

  1. /**********************************************************/
  2. /* File Id.                  Lmenu.C                      */
  3. /* Author.                   Stan Milam.                  */
  4. /* Date Written.             05/08/89.                    */
  5. /*                                                        */
  6. /*         (c) Copyright 1989, 1990 by Stan Milam         */
  7. /*                                                        */
  8. /* Comments:  The routines in this file allow the creation*/
  9. /* and use of Lotus style menus.  Moreover, more than one */
  10. /* Lotus menu per window is allowed.  More than one menu  */
  11. /* can be stacked into one window.  The Mouse can be used */
  12. /* to make selection and scroll the menus or the arrow &  */
  13. /* PgDn/PgUp keys can be used.  Home & End keys move to   */
  14. /* first and last menus respectively.                     */
  15. /**********************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <conio.h>
  21. #include "pcw.i"
  22. #include "pcwproto.h"
  23. #include "menu.h"
  24. #include "keys.h"
  25.  
  26. #define MSGROW  2
  27. #define ITEMROW 1
  28.  
  29. /* Prototype the internal functions */
  30.  
  31. static void change_menu(LMNUTYPE *menu);
  32. static void change_bar_pos(LMNUTYPE *menu, int crnt_bar);
  33. static int  search_menu(LMNUTYPE *menu, int select_char);
  34. static int  search_mouse_select(LMNUTYPE *menu, int col);
  35. static int get_max_bars(LMNUFLDS *ltmp);
  36.  
  37. /***********************************************************/
  38. /*                        Makelmenu                        */
  39. /*                                                         */
  40. /* This function when invoked will draw the Lotus menu     */
  41. /* pointed to by *menu.  See the LMNUTYPE definition in    */
  42. /* menu.h.                                                 */
  43. /***********************************************************/
  44.  
  45. WNDPTR *makelmenu(LMNUTYPE *menu) {
  46.  
  47.     MENU_WND    *lwnd;                                               /* Pointer to menu window */
  48.  
  49.     lwnd = &menu->lwnd;                                              /* Establish adressablity */
  50.     setborder(lwnd->btype);                                          /* Set borders & colors */
  51.     titlecolor(lwnd->tfclr, lwnd->tbclr);
  52.     bordercolor(lwnd->bfclr, lwnd->bbclr);
  53.  
  54.     lwnd->wnd = wframe(lwnd->urow, lwnd->ucol,                       /* Frame the menu window */
  55.                        lwnd->lrow, lwnd->lcol,                       /* and store handle in  */
  56.                        lwnd->fcolor, lwnd->bcolor);                  /* menu structure */
  57.     if (lwnd->wnd == NULL) return(NULL);                             /* Check to see of okay */
  58.  
  59.     lwnd->urow = lwnd->wnd->urow;                                    /* Wframe may have */
  60.     lwnd->ucol = lwnd->wnd->ucol;                                    /* adjusted boundries */
  61.     lwnd->lrow = lwnd->wnd->lrow;
  62.     lwnd->lcol = lwnd->wnd->lcol;
  63.  
  64.     qputchar(lwnd->urow+1,lwnd->ucol,lwnd->bfclr,lwnd->bbclr,24);    /* Draw the arrows */
  65.     qputchar(lwnd->urow+1,lwnd->lcol,lwnd->bfclr,lwnd->bbclr,25);
  66.  
  67.     wtitle(lwnd->wnd, lwnd->tvloc, lwnd->thloc, lwnd->title);        /* Title wnd */
  68.     change_menu(menu);                                               /* Fill window with menu */
  69.     return(lwnd->wnd);                                               /* Contents & return */
  70. }
  71.  
  72. /***********************************************************/
  73. /*                        LmenuInput                       */
  74. /*                                                         */
  75. /* When invoked will manipulate Lotus menu.  Returns the   */
  76. /* select_key in the LMNUFLDS.                             */
  77. /***********************************************************/
  78.  
  79. int lmenuinput(LMNUTYPE *menu) {
  80.  
  81.    LMNUFLDS       *ltmp, **stmp;                                     /* Pointers to menus */
  82.    MENU_WND       *lwnd;                                             /* Pointer the menu parms */
  83.    int ch;                                                           /* For keyin() function */
  84.    int max_bars, max_menus;                                          /* How many menus & bars */
  85.    int crnt_wnd, crnt_bar;                                           /* Keep track menus & bars */
  86.    int row, col, bstatus;                                            /* For Mouse */
  87.  
  88.    stmp = (LMNUFLDS **) menu->llist;
  89.    ltmp = stmp[menu->wnd_pos];                                       /* Get address of 1st menu */
  90.    lwnd = &menu->lwnd;                                               /* Get address of wnd parms */
  91.  
  92.    if (mpresent) hide_mouse();                                       /* Turn the mouse off so */
  93.    re_order(lwnd->wnd,NORMAL);                                       /* We can reorder the windows */
  94.    if (mpresent) show_mouse();                                       /* And finally turn it on */
  95.    for (max_menus = 0;stmp[max_menus] != NULL;max_menus++);
  96.    max_menus--;                                                      /* and adjust */
  97.    max_bars  = get_max_bars(ltmp);                                   /* Get # selects this menu */
  98.    if (mpresent) show_mouse();                                       /* Turn on the mouse */
  99.    for(;;) {                                                         /* Loop forever */
  100.  
  101.       crnt_bar = menu->bar_pos;                                      /* Track current bar pos */
  102.       crnt_wnd = menu->wnd_pos;                                      /* And menu position */
  103.  
  104.  
  105.       ch = keyin();
  106.       switch (ch) {                                               /* Which one? */
  107.          case RITE_MOUSE_KEY :
  108.          case ESC: return(ESC);                                   /* Wants to quit! */
  109.          case BOTH_MOUSE_KEY :
  110.          case ENTER :                                                /* Selects bar pos */
  111.             return(ltmp[menu->bar_pos].select_key);
  112.          case LEFT_MOUSE_KEY :
  113.             get_mpos(&row, &col, &bstatus);                    /* Get row, col, button stat */
  114.             if (row == lwnd->wnd->urow+1) {                    /* Select row? */
  115.                if (search_mouse_select(menu, col)) {           /* If hot spot */
  116.                   change_bar_pos(menu,crnt_bar);               /* Change */
  117.                   return(ltmp[menu->bar_pos].select_key);      /* return */
  118.                }
  119.                else {
  120.                   if (col == lwnd->wnd->ucol) {                /* Up arrow? */
  121.                      menu->wnd_pos--;                          /* Decrement menu index */
  122.                      if (menu->wnd_pos < 0)                    /* Check if okay */
  123.                         menu->wnd_pos = max_menus;            /* No - last menu */
  124.                      menu->bar_pos = 0;                        /* First bar pos */
  125.                      change_menu(menu);                        /* Next menu */
  126.                      ltmp = stmp[menu->wnd_pos];               /* Address new menu */
  127.                      max_bars = get_max_bars(ltmp);            /* # bars new menu */
  128.                   }
  129.                   else {                                       /* Down arrow */
  130.                      if (col == lwnd->wnd->lcol) {
  131.                         menu->wnd_pos++;
  132.                         if (stmp[menu->wnd_pos] == NULL)
  133.                            menu->wnd_pos = 0;
  134.                         menu->bar_pos = 0;
  135.                         change_menu(menu);
  136.                         ltmp = stmp[menu->wnd_pos];
  137.                         max_bars = get_max_bars(ltmp);
  138.                      }
  139.                   }
  140.                }
  141.             }
  142.             break;
  143.          case LEFTARROW :                                         /* Prev bar pos */
  144.          case SHFTTAB :
  145.              menu->bar_pos--;
  146.              if (menu->bar_pos < 0)                               /* Check if < 0 */
  147.                 menu->bar_pos = max_bars;                         /* Set to max bar */
  148.              change_bar_pos(menu, crnt_bar);                      /* Change bar poisition */
  149.              break;
  150.          case RITEARROW :                                         /* Next bar position */
  151.          case TAB :
  152.              menu->bar_pos++;                                     /* Bump & check */
  153.              if (ltmp[menu->bar_pos].select_key == '\0')
  154.                  menu->bar_pos = 0;                               /* First one if at end */
  155.              change_bar_pos(menu, crnt_bar);                      /* Change bars */
  156.              break;
  157.          case UPARROW :                                           /* Prev Menu */
  158.          case PGUP:
  159.              if (max_menus == 0) break;
  160.              menu->wnd_pos--;                                     /* Decrement menu index */
  161.              if (menu->wnd_pos < 0) menu->wnd_pos = max_menus;
  162.              menu->bar_pos = 0;                                   /* Set bar index to first */
  163.              change_menu(menu);                                   /* Put out new menu */
  164.              ltmp = stmp[menu->wnd_pos];                          /* Address new menu */
  165.              max_bars = get_max_bars(ltmp);                       /* Count its selections */
  166.              break;
  167.          case DOWNARROW :                                         /* Next menu */
  168.          case PGDN:
  169.              if (max_menus == 0) break;
  170.              menu->wnd_pos++;                                     /* Bump menu index */
  171.              if (stmp[menu->wnd_pos] == NULL)                     /* See if at end */
  172.                  menu->wnd_pos = 0;                               /* And set to first */
  173.              menu->bar_pos = 0;                                   /* First bar of menu */
  174.              change_menu(menu);                                   /* Put out new menu */
  175.              ltmp = stmp[menu->wnd_pos];                          /* Address new menu */
  176.              max_bars = get_max_bars(ltmp);                       /* Count the selects */
  177.              break;
  178.          case HOME :                                              /* First menu */
  179.              if (menu->wnd_pos == 0) break;
  180.              menu->bar_pos = menu->wnd_pos = 0;
  181.              change_menu(menu);
  182.              ltmp = stmp[0];
  183.              max_bars = get_max_bars(ltmp);
  184.              break;
  185.          case END:                                                /* Last Menu */
  186.              if (menu->wnd_pos == max_menus) break;
  187.              menu->bar_pos = 0;
  188.              menu->wnd_pos = max_menus;
  189.              change_menu(menu);
  190.              ltmp = stmp[menu->wnd_pos];
  191.              max_bars = get_max_bars(ltmp);
  192.              break;
  193.          default :
  194.              if (search_menu(menu, ch)) {                         /* Search for select match */
  195.                 if (crnt_wnd != menu->wnd_pos) {                  /* In another menu? */
  196.                    change_menu(menu);                             /* Put out new menu */
  197.                    ltmp = stmp[menu->wnd_pos];                    /* Address new menu */
  198.                    return(ltmp[menu->bar_pos].select_key);        /* Return */
  199.                 }
  200.                 if (crnt_bar != menu->bar_pos) {                  /* Same menu,another bar */
  201.                    change_bar_pos(menu, crnt_bar);                /* Chg bar pos */
  202.                    return(ltmp[menu->bar_pos].select_key);        /* Return */
  203.                 }
  204.                 else                                              /* Must be crnt bar */
  205.                    return(ltmp[menu->bar_pos].select_key);        /* So Return */
  206.              }
  207.       }
  208.    }
  209. #ifndef __TURBOC__
  210.    return ( (char) 0 );
  211. #endif
  212. }
  213.  
  214. /***********************************************************/
  215. /*                       Change_Menu                       */
  216. /*                                                         */
  217. /* When invoked puts menu pointed to by menu->wnd_pos in   */
  218. /* the window.  Bar position is determined by menu->bar_pos*/
  219. /***********************************************************/
  220.  
  221. static void change_menu(LMNUTYPE *menu) {
  222.  
  223.    int      lcv1, col, length;
  224.    LMNUFLDS *ltmp, **stmp;
  225.    MENU_WND *lwnd;
  226.  
  227.     lwnd = &menu->lwnd;
  228.     stmp = (LMNUFLDS **) menu->llist;
  229.     ltmp = stmp[menu->wnd_pos];
  230.     if (mpresent) hide_mouse();
  231.     clr_wnd(lwnd->wnd, 1);
  232.     for (lcv1 = 0; ltmp[lcv1].select_key != (char) NULL; lcv1++)
  233.         wputs(lwnd->wnd, ITEMROW, ltmp[lcv1].select_col, ltmp[lcv1].item);
  234.  
  235.     col = ltmp[menu->bar_pos].select_col;
  236.     length = strlen(ltmp[menu->bar_pos].item);
  237.     w_chg_attr(lwnd->wnd,ITEMROW, col, lwnd->cfclr, lwnd->cbclr, length);
  238.     wputs(lwnd->wnd, MSGROW, 2, ltmp[menu->bar_pos].item_msg);
  239.     if (mpresent) show_mouse();
  240. }
  241.  
  242. /***********************************************************/
  243. /*                         Search_Menu                     */
  244. /*                                                         */
  245. /* Searches thru all menus looking for a select_key match  */
  246. /* with keyboard input.  All characters are converted to   */
  247. /* upper case.  Returns non-zero if found.  Zero if not    */
  248. /* found.  If a match is found the menu index and bar index*/
  249. /* are changed to point to the selected item.              */
  250. /***********************************************************/
  251.  
  252. static int search_menu(LMNUTYPE *menu, int select_char) {
  253.  
  254.    LMNUFLDS *ltmp, **stmp;                                           /* Menu Pointers */
  255.    int      lcv1, lcv2, ch;                                          /* Index variables */
  256.  
  257.    stmp = (LMNUFLDS **) menu->llist;                                 /* Address menu lists */
  258.    select_char = toupper(select_char);                               /* Uppercase keybd input */
  259.    for (lcv1 = 0; stmp[lcv1] != NULL; lcv1++) {                      /* Get the menu list */
  260.        ltmp = stmp[lcv1];                                            /* One menu list at a time */
  261.        for (lcv2 = 0; ltmp[lcv2].select_key != (char) NULL; lcv2++) {
  262.            ch = (char) toupper(ltmp[lcv2].select_key);               /* Uppercase select_key */
  263.            if (ch == select_char) {                                  /* Do they match ? */
  264.               menu->bar_pos = lcv2;                                  /* Set bar index */
  265.               menu->wnd_pos = lcv1;                                  /* Set menu index */
  266.               return(1);                                             /* Return TRUE */
  267.            }
  268.        }
  269.    }
  270.    return (0);                                                       /* No matches */
  271. }
  272.  
  273. /**********************************************************/
  274. /*                   Search_Mouse_Select                  */
  275. /*                                                        */
  276. /* Runs through all items in a menu to determine if the   */
  277. /* rat was on the item.  If a match is found the bar index*/
  278. /* is updated to reflect the selected item and we return  */
  279. /* a non-zero return code to indicate a match was found.  */
  280. /**********************************************************/
  281.  
  282. static int search_mouse_select(LMNUTYPE *menu, int col) {
  283.  
  284.    MENU_WND *lwnd;
  285.    LMNUFLDS *ltmp, **stmp;
  286.    int      lcv, item_len, item_col;
  287.  
  288.    lwnd = &menu->lwnd;                                               /* Establish Addressability */
  289.    stmp = (LMNUFLDS **) menu->llist;
  290.    ltmp = stmp[menu->wnd_pos];
  291.  
  292.    if (col > lwnd->wnd->ucol) col -= lwnd->wnd->ucol;                /* If inside the window determine column in the window */
  293.    else return(0);                                                   /* Otherwise not in window so exit */
  294.    for (lcv = 0; ltmp[lcv].select_key != '\0'; lcv++) {              /* Search thru all items in list */
  295.         item_col = ltmp[lcv].select_col;                             /* Get items column */
  296.         item_len = (item_col + strlen(ltmp[lcv].item)) - 1;          /* Determine its length on the screen */
  297.         if (col >= item_col && col <= item_len) {                    /* If mouse on the item */
  298.            menu->bar_pos = lcv;                                      /* Set the bar index */
  299.            return(1);                                                /* Return True */
  300.         }
  301.    }
  302.    return(0);                                                        /* No match found */
  303. }
  304.  
  305. /**********************************************************/
  306. /*                    Change_Bar_Pos                      */
  307. /*                                                        */
  308. /* Changes the bar position in the window by changing the */
  309. /* attribute of the current bar to normal window attribute*/
  310. /* and changing the attribute of the new item to the color*/
  311. /* specified for bar color.  Got it.  Okay, test in five  */
  312. /* minutes!                                               */
  313. /**********************************************************/
  314.  
  315. static void change_bar_pos(LMNUTYPE *menu, int crnt_bar) {
  316.  
  317.    int      row, col, length;
  318.    LMNUFLDS *ltmp, **stmp;
  319.    MENU_WND *lwnd;
  320.  
  321.    lwnd = &menu->lwnd;                                               /* Establish addressability */
  322.    stmp = (LMNUFLDS **) menu->llist;
  323.    ltmp = stmp[menu->wnd_pos];
  324.    if (mpresent) hide_mouse();                                       /* If rat home hide from neighbors! */
  325.    length = strlen(ltmp[crnt_bar].item);                             /* Get length of item on screen */
  326.    col    = ltmp[crnt_bar].select_col;                               /* Get its column */
  327.    w_chg_attr(lwnd->wnd,ITEMROW,col,lwnd->fcolor,lwnd->bcolor,length);/* Change its color attribute */
  328.  
  329.    length = strlen(ltmp[menu->bar_pos].item);                        /* Get length of new item */
  330.    col    = ltmp[menu->bar_pos].select_col;                          /* Get its column */
  331.    w_chg_attr(lwnd->wnd,ITEMROW,col, lwnd->cfclr, lwnd->cbclr,length);/* Change its color attribute */
  332.  
  333.    col = lwnd->wnd->ucol + 1;                                        /* Now, must clear the message line */
  334.    row = lwnd->wnd->urow + 2;
  335.    length = (lwnd->wnd->lcol - 1) - col;
  336.    qhchar(row, col, lwnd->fcolor, lwnd->bcolor, 32, length);         /* Clear the line */
  337.    wputs(lwnd->wnd, 2,2, ltmp[menu->bar_pos].item_msg);              /* And write then new message */
  338.    if (mpresent) show_mouse();                                       /* Finally turn back on the mouse */
  339. }
  340.  
  341. /**********************************************************/
  342. /*                      Get_Max_Bars                      */
  343. /*                                                        */
  344. /* Used to count how many selections for a given menu.    */
  345. /**********************************************************/
  346.  
  347. static int get_max_bars(LMNUFLDS *ltmp) {
  348.  
  349.     int i;
  350.  
  351.     for (i = 0; ltmp[i].select_key != '\0'; i++); i--;
  352.     return(i);
  353. }
  354.